package com.lanhao.aot.carrierintegration.usps;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.List;
import java.util.UUID;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.openservices.shade.org.apache.commons.lang3.StringUtils;
import com.google.common.collect.Lists;
import com.lanhao.aot.carrierintegration.commondto.LabelApplyRequestDTO;
import com.lanhao.aot.carrierintegration.commondto.LabelTrackResponseDTO;
import com.lanhao.aot.util.BigDecimalUtil;
import com.lanhao.aot.util.Dom4jUtil;

import cn.hutool.core.codec.Base64;
import cn.hutool.http.HttpUtil;

public class UspsAPIUtil {
	private static final Logger LOG = LoggerFactory.getLogger(UspsAPIUtil.class);
	public static final String labelUrl = "https://stg-secure.shippingapis.com/ShippingAPI.dll?API=eVS&XML=";
	public static final String trackUrl = "https://stg-secure.shippingapis.com/ShippingAPI.dll?API=TrackV2&XML=";
	public static final String cancelUrl = "https://secure.shippingapis.com/ShippingAPI.dll?API=eVSCancel&XML=";
	public static final String USERID = "844MACHP4345";

	public static BigDecimal cm2inch = new BigDecimal("0.3937008"); // 厘米 -> 英寸
	public static BigDecimal lb2oz = new BigDecimal("16"); // 磅 -> 盎司
	public static BigDecimal g2oz = new BigDecimal("0.035274"); // 克 -> 盎司
	public static BigDecimal kg2oz = new BigDecimal("35.2739619"); // 千克 -> 盎司

	public static BigDecimal serviceWeight = new BigDecimal("16.000"); // 区分类型的重量区分点

	public static void main(String[] args) {
		List<LabelApplyRequestDTO> addressList = Lists.newArrayList();
		LabelApplyRequestDTO address1 = new LabelApplyRequestDTO();
		address1.setFromName("Chuanbo Li");
		address1.setFromFirm("Li");
		address1.setFromAddress2("1424 Newbridge Ave");
		address1.setFromZip5("94401");
		address1.setFromCity("San Mateo");
		address1.setFromState("CA");

		address1.setToName("Clare Teng");
		address1.setToFirm("Teng");
		address1.setToCity("Philadelphia");
		address1.setToState("PA");
		address1.setToAddress2("2101 Chestnut st. Apt 1720");
		address1.setToZip5("19103");

		address1.setWeight(new BigDecimal("5").multiply(lb2oz));
		address1.setLength(new BigDecimal("20").multiply(cm2inch));
		address1.setWidth(new BigDecimal("20").multiply(cm2inch));
		address1.setHeight(new BigDecimal("30").multiply(cm2inch));
		addressList.add(address1);

		LabelApplyRequestDTO address2 = new LabelApplyRequestDTO();
		address2.setFromName("Chuanbo Li");
		address2.setFromFirm("Li");
		address2.setFromAddress2("1424 Newbridge Ave");
		address2.setFromZip5("94401");
		address2.setFromCity("San Mateo");
		address2.setFromState("CA");

		address2.setToName("Yifei Li");
		address2.setToFirm("Li");
		address2.setToCity("Glendora");
		address2.setToState("CA");
		address2.setToAddress2("445 N Live Oak Ave");
		address2.setToZip5("91741");

		address2.setWeight(new BigDecimal("5").multiply(lb2oz));
		address2.setLength(new BigDecimal("20").multiply(cm2inch));
		address2.setWidth(new BigDecimal("20").multiply(cm2inch));
		address2.setHeight(new BigDecimal("30").multiply(cm2inch));

		addressList.add(address2);

		LabelApplyRequestDTO address3 = new LabelApplyRequestDTO();
		address3.setFromName("Chuanbo Li");
		address3.setFromFirm("Li");
		address3.setFromAddress2("1424 Newbridge Ave");
		address3.setFromZip5("94401");
		address3.setFromCity("San Mateo");
		address3.setFromState("CA");

		address3.setToName("Xiaopeng Qu");
		address3.setToFirm("Qu");
		address3.setToCity("Berkerly Heights");
		address3.setToState("NJ");
		address3.setToAddress2("41 Meadowview Ln");
		address3.setToZip5("07922");

		address3.setWeight(new BigDecimal("350").multiply(g2oz));
		address3.setLength(new BigDecimal("10").multiply(cm2inch));
		address3.setWidth(new BigDecimal("15").multiply(cm2inch));
		address3.setHeight(new BigDecimal("15").multiply(cm2inch));

		addressList.add(address3);

		LabelApplyRequestDTO address4 = new LabelApplyRequestDTO();
		address4.setFromName("Xiaopeng Qu");
//		address4.setFromFirm("Qu");
		address4.setFromAddress2("41 Meadowview Ln");
		address4.setFromZip5("07922");
		address4.setFromCity("Berkerly Heights");
		address4.setFromState("NJ");

		address4.setToName("Clare Teng");
//		address4.setToFirm("Teng");
		address4.setToCity("Philadelphia");
		address4.setToState("PA");
		address4.setToAddress2("2101 Chestnut st. Apt 1720");
		address4.setToZip5("19103");

		address4.setWeight(new BigDecimal("1").multiply(lb2oz));
		address4.setLength(new BigDecimal("10").multiply(cm2inch));
		address4.setWidth(new BigDecimal("20").multiply(cm2inch));
		address4.setHeight(new BigDecimal("30").multiply(cm2inch));
		addressList.add(address4);

		LabelApplyRequestDTO address5 = new LabelApplyRequestDTO();
		address5.setFromName("Xiaopeng Qu");
		address5.setFromFirm("Qu");
		address5.setFromAddress2("41 Meadowview Ln");
		address5.setFromZip5("07922");
		address5.setFromCity("Berkerly Heights");
		address5.setFromState("NJ");

		address5.setToName("Yifei Li");
		address5.setToFirm("Li");
		address5.setToCity("Glendora");
		address5.setToState("CA");
		address5.setToAddress2("445 N Live Oak Ave");
		address5.setToZip5("91741");

		address5.setWeight(new BigDecimal("2").multiply(lb2oz));
		address5.setLength(new BigDecimal("10").multiply(cm2inch));
		address5.setWidth(new BigDecimal("20").multiply(cm2inch));
		address5.setHeight(new BigDecimal("30").multiply(cm2inch));

		addressList.add(address5);

		LabelApplyRequestDTO address6 = new LabelApplyRequestDTO();
		address6.setFromName("Xiaopeng Qu");
		address6.setFromFirm("Qu");
		address6.setFromAddress2("41 Meadowview Ln");
		address6.setFromZip5("07922");
		address6.setFromCity("Berkerly Heights");
		address6.setFromState("NJ");

		address6.setToName("Chuanbo Li");
		address6.setToFirm("Li");
		address6.setToCity("San Mateo");
		address6.setToState("CA");
		address6.setToAddress2("1424 Newbridge Ave");
		address6.setToZip5("94401");

		address6.setWeight(new BigDecimal("400").multiply(g2oz));
		address6.setLength(new BigDecimal("10").multiply(cm2inch));
		address6.setWidth(new BigDecimal("15").multiply(cm2inch));
		address6.setHeight(new BigDecimal("15").multiply(cm2inch));

		addressList.add(address6);

//		for (int i = 0; i < addressList.size(); i++) {
//			RequestAddressInfo address = addressList.get(i);
//		}
//		getLabelFileInfo(address4, 3);
//		doLabelCancel("420063719200190289381600000084");
		List<String> trackIdList = Lists.newArrayList();
		trackIdList.add("9202090256754700222046");
//		trackIdList.add("9202090256754600375330");
//		trackIdList.add("9202090256754600380563");
//		List<LabelTrackInfo> labelTrackInfo = getLabelTrackInfo(trackIdList, "TrackRequest"); // TrackRequest或TrackFieldRequest
//		LOG.info("获取面单轨迹信息返回labelTrackInfo={}", labelTrackInfo.toString());
		
		System.out.println(trackUrl.replaceAll("stg-secure", "secure"));
	}

	public static String getLabelFileInfo(LabelApplyRequestDTO address, int index) {
		String fileType = "PDF";
		StringBuilder eVSRequest = new StringBuilder();
		eVSRequest.append("<eVSRequest USERID=\"" + USERID + "\">");
		eVSRequest.append("<Option>1</Option>");
		eVSRequest.append("<Revision></Revision>");
		eVSRequest.append("<ImageParameters>");
		eVSRequest.append("<ImageParameter>4x6LABELP</ImageParameter>");
		eVSRequest.append("<XCoordinate>0</XCoordinate>");
		eVSRequest.append(" <YCoordinate>900</YCoordinate>");
		eVSRequest.append("</ImageParameters>");
		eVSRequest.append("<FromName>" + address.getFromName() + "</FromName>");
		String fromFirm = StringUtils.isNotBlank(address.getFromFirm()) ? address.getFromFirm() : "";
		eVSRequest.append("<FromFirm>" + fromFirm + "</FromFirm>");
		String fromAddress1 = StringUtils.isNotBlank(address.getFromAddress1()) ? address.getFromAddress1() : "";
		eVSRequest.append("<FromAddress1>" + fromAddress1 + "</FromAddress1>");
		eVSRequest.append("<FromAddress2>" + address.getFromAddress2() + "</FromAddress2>");
		eVSRequest.append("<FromCity>" + address.getFromCity() + "</FromCity>");
		eVSRequest.append("<FromState>" + address.getFromState() + "</FromState>");
		eVSRequest.append("<FromZip5>" + address.getFromZip5() + "</FromZip5>"); // 前五位数字，所在州，所在城市，所在地区的的邮编，必填
		String fromZip4 = StringUtils.isNotBlank(address.getFromZip4()) ? address.getFromZip4() : "";
		eVSRequest.append("<FromZip4>" + fromZip4 + "</FromZip4>"); // 非必填
		String fromPhone = StringUtils.isNotBlank(address.getFromPhone()) ? address.getFromPhone() : "";
		eVSRequest.append("<FromPhone>" + fromPhone + "</FromPhone>");
		eVSRequest.append("<AllowNonCleansedOriginAddr>true</AllowNonCleansedOriginAddr>");

		eVSRequest.append("<ToName>" + address.getToName() + "</ToName>");
		String toFirm = StringUtils.isNotBlank(address.getToFirm()) ? address.getToFirm() : "";
		eVSRequest.append("<ToFirm>" + toFirm + "</ToFirm>");
		String toAddress1 = (StringUtils.isNotBlank(address.getToAddress1()) ? address.getToAddress1() : "");
		eVSRequest.append("<ToAddress1>" + toAddress1 + "</ToAddress1>");
		eVSRequest.append("<ToAddress2>" + address.getToAddress2() + "</ToAddress2>");
		eVSRequest.append("<ToCity>" + address.getToCity() + "</ToCity>");
		eVSRequest.append("<ToState>" + address.getToState() + "</ToState>");
		eVSRequest.append("<ToZip5>" + address.getToZip5() + "</ToZip5>");
		String toZip4 = StringUtils.isNotBlank(address.getToZip4()) ? address.getToZip4() : "";
		eVSRequest.append("<ToZip4>" + toZip4 + "</ToZip4>");
		String toPhone = StringUtils.isNotBlank(address.getToPhone()) ? address.getToPhone() : "";
		eVSRequest.append("<ToPhone>" + toPhone + "</ToPhone>");
		eVSRequest.append("<AllowNonCleansedDestAddr>true</AllowNonCleansedDestAddr>");

		// 此处FIRST CLASS和PRIORITY有所不一样 16盎司为分割线
//		eVSRequest.append("<WeightInOunces>12.0000</WeightInOunces>");
//		eVSRequest.append("<ServiceType>FIRST CLASS</ServiceType>");
//		eVSRequest.append("<Container>PACKAGE SERVICE</Container>");
//		eVSRequest.append("<Width></Width>");
//		eVSRequest.append("<Length></Length>");
//		eVSRequest.append("<Height></Height>");
//		eVSRequest.append("<Machinable></Machinable>");
//		eVSRequest.append("<CustomerRefNo>FC</CustomerRefNo>");
		BigDecimal weight = address.getWeight();
		eVSRequest.append("<WeightInOunces>" + BigDecimalUtil.getBigDecimal(weight) + "</WeightInOunces>");
		if (weight.compareTo(serviceWeight) > -1) {
			eVSRequest.append("<ServiceType>PRIORITY</ServiceType>");
			eVSRequest.append("<Container>RECTANGULAR</Container>");
		} else {
			eVSRequest.append("<ServiceType>FIRST CLASS</ServiceType>");
			eVSRequest.append("<Container>PACKAGE SERVICE</Container>");
		}
		eVSRequest.append("<Width>" + BigDecimalUtil.getBigDecimal(address.getWidth()) + "</Width>"); // 英寸
		eVSRequest.append("<Length>" + BigDecimalUtil.getBigDecimal(address.getLength()) + "</Length>");// 英寸
		eVSRequest.append("<Height>" + BigDecimalUtil.getBigDecimal(address.getHeight()) + "</Height>");// 英寸
		eVSRequest.append("<Machinable></Machinable>");
		eVSRequest.append("<CustomerRefNo></CustomerRefNo>");

		eVSRequest.append("<ExtraServices>");
		eVSRequest.append("<ExtraService>155</ExtraService>");
		eVSRequest.append("</ExtraServices>");

		eVSRequest.append("<ReceiptOption>None</ReceiptOption>");
		eVSRequest.append("<ImageType>" + fileType + "</ImageType>");
		eVSRequest.append("<PrintCustomerRefNo>true</PrintCustomerRefNo>");
		eVSRequest.append("</eVSRequest>");

		try {
			String xmlParam = java.net.URLEncoder.encode(eVSRequest.toString(), "UTF-8");
			String labelInfoResult = HttpUtil.get(labelUrl + xmlParam, 5000);
			LOG.info("labelInfoResult:\r\n" + labelInfoResult);
			Document doc = DocumentHelper.parseText(labelInfoResult);
			// 返回参数进行组装
			JSONObject response = new JSONObject();
			Dom4jUtil.dom4j2Json(doc, response);
			LOG.info("获取面单信息url={}, response={}", labelUrl + eVSRequest.toString(), response);
			JSONObject eVSResponse = response.getJSONObject("eVSResponse");
			String barcodeNumber = StringUtils.EMPTY;
			// 成功的情况下
			if (eVSResponse != null) {
				barcodeNumber = eVSResponse.getString("BarcodeNumber");
				String labelImage = eVSResponse.getString("LabelImage");
				File labelFile = Base64.decodeToFile(labelImage, new File("D:/testLabel/"
						+ UUID.randomUUID().toString().replaceAll("-", "") + "_" + index + "." + fileType));
				LOG.info("获取标签信息成功，运单号BarcodeNumber={}，文件保存路径：{}", barcodeNumber, labelFile.getAbsolutePath());
			} else {
				JSONObject errorResponse = response.getJSONObject("Error");
				String description = errorResponse.getString("Description");
				String number = errorResponse.getString("Number");
				String source = errorResponse.getString("Source");
				LOG.info("获取标签失败，number={},description={},source={}", number, description, source);
			}
			// 失败的情况下
			return barcodeNumber;
		} catch (UnsupportedEncodingException | DocumentException e) {
			e.printStackTrace();
		}
		return StringUtils.EMPTY;
	}

	public static boolean doLabelCancel(String mailNo) {
		StringBuilder cancelRequest = new StringBuilder();
		try {
			cancelRequest.append("<eVSCancelRequest USERID=\"" + USERID + "\">");
			cancelRequest.append("<BarcodeNumber>" + mailNo + "</BarcodeNumber>");
			cancelRequest.append("</eVSCancelRequest>");
			String xmlParam = java.net.URLEncoder.encode(cancelRequest.toString(), "UTF-8");
			String trackInfoResult = HttpUtil.get(cancelUrl + xmlParam, 5000);
			LOG.info("请求USPS面单取消接口请求信息url={}，response={}", cancelUrl + cancelRequest.toString(), trackInfoResult);
			Document doc = DocumentHelper.parseText(trackInfoResult);
			// 返回参数进行组装
			JSONObject response = new JSONObject();
			Dom4jUtil.dom4j2Json(doc, response);
			JSONObject eVSCancelResponse = response.getJSONObject("eVSCancelResponse");
			// 成功的情况下
			if (eVSCancelResponse != null) {
				String barcodeNumber = eVSCancelResponse.getString("BarcodeNumber");
				String status = eVSCancelResponse.getString("Status");
				String reason = eVSCancelResponse.getString("Reason");
				LOG.info("取消标签接口返回信息:BarcodeNumber={}, status={}, reason={}", barcodeNumber, status, reason);
				return "Cancelled".equals(status);
			} else {
				LOG.info("取消标签失败");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return Boolean.FALSE;
	}

	public static List<LabelTrackResponseDTO> getLabelTrackInfo(List<String> trackIdList, String apiType) {
		List<LabelTrackResponseDTO> trackInfoList = Lists.newArrayList();
		StringBuilder trackRequest = new StringBuilder();
		trackRequest.append("<" + apiType + " USERID=\"" + USERID + "\">");
		if ("TrackFieldRequest".equals(apiType)) {
			trackRequest.append("<Revision>1</Revision>");
			trackRequest.append("<ClientIp>127.0.0.1</ClientIp>");
			trackRequest.append("<SourceId>Machpak</SourceId>");
		}
		for (int i = 0; i < trackIdList.size(); i++) {
			trackRequest.append("<TrackID ID=\"" + trackIdList.get(i) + "\"> </TrackID>");
		}
		trackRequest.append("</" + apiType + ">");
		try {
			String xmlParam = java.net.URLEncoder.encode(trackRequest.toString(), "UTF-8");
			String trackInfoResult = HttpUtil.get(trackUrl + xmlParam, 5000);
			LOG.info("trackInfoResult:\r\n" + trackInfoResult);
			Document doc = DocumentHelper.parseText(trackInfoResult);
			// 返回参数进行组装
			JSONObject response = new JSONObject();
			Dom4jUtil.dom4j2Json(doc, response);
			LOG.info("请求USPS轨迹接口请求信息url={},response={}", trackUrl + trackRequest.toString(), response);
			JSONObject trackResponse = response.getJSONObject("TrackResponse");
			JSONArray trackInfoArray = null;
			if(trackIdList.size() > 1) {
				trackInfoArray = trackResponse.getJSONArray("TrackInfo"); // 只有一个情况下是JSONObject
			} else {
				trackInfoArray = new JSONArray();
				JSONObject trackInfoObject = trackResponse.getJSONObject("TrackInfo");
				trackInfoArray.add(trackInfoObject);
			}
			if (trackInfoArray != null) {
				for (int i = 0; i < trackInfoArray.size(); i++) {
					LabelTrackResponseDTO labelTrackInfo = new LabelTrackResponseDTO();
					JSONObject trackInfo = trackInfoArray.getJSONObject(i);
					String labelNo = trackInfo.getString("@ID");
					labelTrackInfo.setLabelNo(labelNo);
					JSONObject errorObject = trackInfo.getJSONObject("Error");
					if (errorObject != null) {
						String description = errorObject.getString("Description");
						String number = errorObject.getString("Number");
						labelTrackInfo.setErrorInfo(description);
						labelTrackInfo.setLabelNo(number);
					} else {
						String trackSummary = trackInfo.getString("TrackSummary");
						String trackDetail = trackInfo.getString("TrackDetail");
						labelTrackInfo.setTrackSummary(trackSummary);
						List<String> trackDetailList = Lists.newArrayList(trackDetail);
						labelTrackInfo.setTrackDetailList(trackDetailList);
					}
					trackInfoList.add(labelTrackInfo);
				}
			}
		} catch (UnsupportedEncodingException | DocumentException e) {
			e.printStackTrace();
		}
		return trackInfoList;
	}

}
